package com.googlecode.yoohoo.osgi;

import java.util.Dictionary;
import java.util.Hashtable;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;

import com.googlecode.yoohoo.config.IConfigManager;
import com.googlecode.yoohoo.message.IMessageManager;
import com.googlecode.yoohoo.message.MessageManager;
import com.googlecode.yoohoo.utils.Constants;
import com.googlecode.yoohoo.utils.OsgiUtils;

public abstract class AbstractBundleActivator implements BundleActivator {
	private static final String KEY_CONFIG_MANAGER = "YooHoo-Config-Manager";
	
	protected IConfigManager configManager;
	protected ServiceRegistration configManagerRegistration;
	protected ServiceRegistration messageManagerRegistration;
	
	@Override
	public void start(BundleContext context) throws Exception {
		loadConfig(context);
		loadMessage(context);
		doStart(context);
	}

	private void loadMessage(BundleContext context) {
		if (context.getBundle().getResource(IMessageManager.DEFAULT_I18N_PATH) != null) {
			IMessageManager messageManager = new MessageManager(context);
			Dictionary<Object, Object> properties = new Hashtable<Object, Object>();
			properties.put(IMessageManager.MESSAGE_MANAGER_BUNDLE_SYMBOLIC_NAME, OsgiUtils.getSymbolicName(context.getBundle()));
			messageManagerRegistration = context.registerService(IMessageManager.class.getName(),
					messageManager, properties);
		}
	}

	protected void loadConfig(BundleContext context) throws Exception {
		configManager = getConfigManager(context);
		if (configManager == null)
			return;
		
		if (configManager instanceof IBundleContextAware) {
			((IBundleContextAware)configManager).setBundleContext(context);
		}
		
		configManager.load();
		
		Dictionary<Object, Object> properties = new Hashtable<Object, Object>();
		properties.put(Constants.KEY_BUNDLE_SYMBOLIC_NAME, OsgiUtils.getSymbolicName(context.getBundle()));
		configManagerRegistration = context.registerService(IConfigManager.class.getName(), configManager, properties);
	}

	@SuppressWarnings("unchecked")
	protected IConfigManager getConfigManager(BundleContext context) throws Exception {
		Dictionary<String, String> headers = context.getBundle().getHeaders();
		String configManagerClassString = headers.get(KEY_CONFIG_MANAGER);
		if (configManagerClassString == null)
			return null;
		
		Class<?> configManagerClass = context.getBundle().loadClass(configManagerClassString);
		if (!IConfigManager.class.isAssignableFrom(configManagerClass)) {
			throw new IllegalArgumentException(String.format("Config manager class '%s' which from bundle '%s' should implement %s interface.",
					configManagerClassString, OsgiUtils.getSymbolicName(context.getBundle()), IConfigManager.class.getName()));
		}
		
		return (IConfigManager)configManagerClass.newInstance();
	}

	@Override
	public void stop(BundleContext context) throws Exception {
		doStop(context);
		unloadMessage(context);
		unloadConfig(context);
	}

	private void unloadMessage(BundleContext context) {
		if (messageManagerRegistration != null) {
			messageManagerRegistration.unregister();
		}
	}

	protected void unloadConfig(BundleContext context) {
		if (configManagerRegistration != null)
			configManagerRegistration.unregister();
	}

	protected abstract void doStart(BundleContext context) throws Exception;
	protected abstract void doStop(BundleContext context) throws Exception;	
}
